using MarkDownFileSplitter.AIAnalaysis;
using MarkDownFileSplitter.AIDelete;
using MarkDownFileSplitter.Htm;
using MarkDownFileSplitter.Markdown;
using MarkDownFileSplitter.Meilisearch;
using MarkDownFileSplitter.Pdf;
using Newtonsoft.Json.Linq;
using System.Diagnostics;
using System.Runtime.Intrinsics.Arm;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using System.Data;

namespace MarkDownFileSplitter
{
    public partial class Form1 : Form
    {
        private MarkdownFileContent m_currentContent;
        private string m_lastFileName;

        private bool m_enableAutoCheck = true;
        private DifyFileUploader m_difyFileUploader;
        private string currentTxtFilePath;

        private MarkdownFileContentItem m_selectedItem;
        private TreeNode m_selectedTreeNode;

        public Form1()
        {
            InitializeComponent();

            Text = "奥格知识库管理工具 v"+this.GetType().Assembly.GetFileVersion();
        }

        /// <summary>
        /// TreeView中显示Markdown的章节它的章节是以#、##、### 包含的三级目录。
        /// 可以选中很多Node，然后在右侧的RichText中显示这些文字。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            treeView1.CheckBoxes = true;
            treeView1.AfterSelect += (s, args) =>
            {
                richTextBox1.Clear();
                TreeNode node = treeView1.SelectedNode;
                {
                    if (node.Tag != null)
                    {
                        // 假设 node.Tag 是 MarkdownFileContentItem 类型
                        var markdownItem = (MarkdownFileContentItem)node.Tag;
                        m_selectedItem = markdownItem;
                        m_selectedTreeNode = node;

                        // 获取开始行和结束行
                        int startRow = markdownItem.StartRowIndex;
                        int endRow = markdownItem.EndRowIndex;
                        // 将对应行的内容添加到 richTextBox1 中
                        for (int i = startRow; i <= endRow; i++)
                        {
                            if (i >= m_currentContent.ContentLines.Length)
                                continue;
                            richTextBox1.AppendText(m_currentContent.ContentLines[i] + Environment.NewLine);
                        }
                        //获取节点的已AI总结的内容
                        textBox1.Text = GetMainKey(node);
                        if (markdownItem.AIDescription != null)
                            textBox1.Text += markdownItem.AIDescription;
                    }
                }
            };

            treeView1.AfterCheck += (s, args) =>
            {
                if (m_enableAutoCheck)
                    ExportTitle();
            };
        }
        /// <summary>
        /// 打开一个Markdown文件，然后在TreeView中显示他的章节。它的章节是以#、##、### 包含的三级目录。
        /// TreeNode要记住他对于的文档内容。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_openFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Markdown Files|*.md|HTM Files|*.htm;*.html|PDF Files|*.pdf";
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                string filePath = openFileDialog.FileName;
                m_lastFileName = filePath;

                string markdownFilePath;
                string extension = Path.GetExtension(filePath).ToLower();
                bool bReadMd = true;
                if (extension == ".md")
                {
                    ReadMarkdownFile(filePath);
                    markdownFilePath = filePath;
                }
                else if (extension == ".htm" || extension == ".html")
                {
                    bReadMd = ReadHtmFile(filePath);
                    markdownFilePath = Path.ChangeExtension(filePath, ".md");
                }
                else if (extension == ".pdf")
                {
                    bReadMd = ReadPdfFile(filePath);
                    markdownFilePath = Path.ChangeExtension(filePath, ".md");
                }
                else
                {
                    return;
                }

                if (bReadMd && File.Exists(markdownFilePath))
                {
                    ReadMarkdownFile(markdownFilePath);
                }
            }
        }

        #region 展示内容
        private void ReadMarkdownFile(string filePath)
        {
            m_currentContent = new MarkdownFileContent(filePath);
            m_currentContent.OnLoad = (s2, e2) =>
            {
                treeView1.Nodes.Clear(); // 清空TreeView
                foreach (MarkdownFileContentItem rootItem in m_currentContent.RootItems)
                {
                    TreeNode rootNode = CreateTreeNode(rootItem);
                    treeView1.Nodes.Add(rootNode);
                }

                // 递归创建TreeNode的方法
                TreeNode CreateTreeNode(MarkdownFileContentItem item)
                {
                    TreeNode node = new TreeNode(item.Title);

                    node.Tag = item;
                    foreach (MarkdownFileContentItem child in item.Children)
                    {
                        TreeNode childNode = CreateTreeNode(child);
                        node.Nodes.Add(childNode);
                    }
                    return node;
                }
            };
            m_currentContent.LoadFile();
        }
        #endregion

        private bool ReadHtmFile(string filePath)
        {
            FormHeadingMarker formHeadingMarker = new FormHeadingMarker(filePath, InputFileType.Htm);
            return formHeadingMarker.ShowDialog() == DialogResult.OK;
        }

        private bool ReadPdfFile(string filePath)
        {
            FormHeadingMarker formHeadingMarker = new FormHeadingMarker(filePath, InputFileType.Pdf);
            return formHeadingMarker.ShowDialog() == DialogResult.OK;
        }

        #region 获得当前节点
        /// <summary>
        /// 清除TreeView的所有Check的节点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_clearSelection_Click(object sender, EventArgs e)
        {
            ClearCheckedNodes(treeView1.Nodes);
        }

        private void ClearCheckedNodes(TreeNodeCollection nodes)
        {
            foreach (TreeNode node in nodes)
            {
                node.Checked = false;
                ClearCheckedNodes(node.Nodes);
            }
        }
        #endregion

        #region 输出文档
        /// <summary>
        /// 同ExportTitle一样，但是要导出一个新的markdown文档。
        /// 这个新的markdown文档存储ExportTitle那里章节等于2级的内容。
        /// 
        /// 存储的markdown文档跟m_lastFileName同目录，但是标记为1,2,3....不能重名，并设导出的名词为xxn.md
        /// 
        /// 另外再写一个txt文件，存储{text1.txt}+'.'+'文档在:'+{textBox2.txt}+m_lastFileName最后一级目录+xxn.md
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_exportFile_Click(object sender, EventArgs e)
        {
            m_enableAutoFileIndex = true;
            m_autoFileIndex = 0;
            ExportFile();
        }
        private bool m_enableAutoFileIndex = false;
        private int m_autoFileIndex = 0;
        private string ExportFile()
        {
            if (treeView1.Nodes.Count == 0)
                return null;
            StringBuilder markdownContent = new StringBuilder();
            if (treeView1.Nodes[0].Checked)
            {
                MarkdownFileContentItem level1Node = treeView1.Nodes[0].Tag as MarkdownFileContentItem;
                level1Node.AppendTo(m_currentContent.ContentLines, markdownContent);
            }
            else
            {
                foreach (TreeNode level1Node in treeView1.Nodes)
                {
                    foreach (TreeNode level2Node in level1Node.Nodes)
                    {
                        if (level2Node.Checked)
                        {
                            var markdownItem = (MarkdownFileContentItem)level2Node.Tag;
                            markdownItem.AppendTo(m_currentContent.ContentLines, markdownContent);
                        }
                    }
                }
            }


            string directory = Path.GetDirectoryName(m_lastFileName);
            int index = m_autoFileIndex;
            string markdownFileName;
            var fileName = Path.GetFileNameWithoutExtension(m_lastFileName);
            do
            {
                markdownFileName = Path.Combine(directory, fileName + $"{index}.md");
                index++;
                if (m_enableAutoFileIndex == false)
                {
                    break;
                }
            } while (File.Exists(markdownFileName));
            SaveFile(markdownFileName, markdownContent.ToString());

            string txtFileName = Path.Combine(directory, "text" + fileName + ".txt");
            var dir = Path.GetFileName(Path.GetDirectoryName(m_lastFileName));
            dir = "";


            string txtContent = $"{textBox1.Text}文档在:<a>{GlobalSetting.Instance.MinIOUrl}{dir}/{Path.GetFileName(markdownFileName)}</a>";

            if (m_autoFileIndex == 1)
            {
                if (File.Exists(txtFileName))
                {
                    File.Delete(txtFileName);
                }
            }

            File.AppendAllText(txtFileName, txtContent);
            File.AppendAllText(txtFileName, "\r\n\r\n");
            currentTxtFilePath = txtFileName;
            return markdownFileName;
        }

        private void SaveFile(string filePath, string content)
        {
            File.WriteAllText(filePath, content, Encoding.Unicode);
        }
        #endregion

        #region 上传
        private async Task UploadToMinio(string filePath)
        {
            if (uploadToMinioCheckBox.Checked && Path.GetExtension(filePath).Equals(".md"))
            {
                await MinioFileUploader.Upload(filePath);
            }
        }
        private async Task UploadToDify(string filePath)
        {
            if (uploadToServeCheckBox.Checked)
            {
                if (m_difyFileUploader == null)
                {
                    m_difyFileUploader = new DifyFileUploader(apiKey: "dataset-VmYPbWdIV8LHwhmJPUpZToCq", baseUrl: "http://192.168.2.231:480/");
                }

                if (filePath == null)
                    return;

                string datasetId = "9f1bb6fb-3f60-43ba-a758-a39401696df5";
                var uploadResult = await m_difyFileUploader.UploadDocument(datasetId, filePath);

                // 等待文档索引完成
                string documentId = uploadResult["document"]["id"].ToString();
                bool isCompleted = false;
                while (!isCompleted)
                {
                    if (await m_difyFileUploader.GetIndexingStatus(datasetId, uploadResult["batch"].ToString()))
                    {
                        isCompleted = true;
                    }
                    else
                    {
                        await Task.Delay(1000); // 等待1秒后重试
                    }
                }

                //查询文档分段
                var queryResult = await m_difyFileUploader.QuerySegments(datasetId, documentId);

                //重新提取关键词
                JArray dataArr = (JArray)queryResult["data"];
                //遍历数组，取content，传给AI，将返回的结果构建成数组，替换掉原来的keywords
                foreach (JToken data in dataArr)
                {
                    string answer = OllamaUtils.SendChatRequest($"提取以下文字的关键词，不要输出额外文字，只要关键词，关键词之间用逗号分隔：{data["content"]}");
                    string[] keywords = answer.Split(",");
                    //data["keywords"] = ;
                    //更新文档分段
                    var updateResult = m_difyFileUploader.UpdateSegment(datasetId, documentId, data["id"].ToString(), data["content"].ToString(), JArray.FromObject(keywords));
                }
            }
        }
        #endregion

        #region 总结内容
        private TreeNode GetSelectedNode()
        {
            if (treeView1.Nodes.Count == 0)
                return null;

            TreeNode selectedNode = null;
            if (treeView1.Nodes[0].Checked)
            {
                selectedNode = treeView1.Nodes[0];
            }
            else
            {
                foreach (TreeNode level1Node in treeView1.Nodes)
                {
                    foreach (TreeNode level2Node in level1Node.Nodes)
                    {
                        if (level2Node.Checked)
                        {
                            selectedNode = level2Node;
                        }
                    }
                }
            }
            return selectedNode;
        }
        /// <summary>
        /// 收集所有二级TreeNode被Check的节点。
        /// 然后在textBox1中设置如下格式的文档,
        /// 关于{一级节点的Title}的{二级节点的Title}，包括了{三级节点的Title}等功能
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExportTitle()
        {
            var selectedNode = GetSelectedNode();
            if (selectedNode == null)
                return;

            textBox1.Text = GetMainKey(selectedNode);
            var markdownItem = selectedNode.Tag as MarkdownFileContentItem;
            if (markdownItem.AIDescription != null)
                textBox1.Text += markdownItem.AIDescription;
        }

        private string GetMainKey(TreeNode level2Node)
        {
            if (level2Node == null) return "";
            StringBuilder output = new StringBuilder();

            var level1Node = level2Node.Parent as TreeNode;
            string level1Title = "";
            if (level1Node == null)
            {
                level1Title = GetMainText(level2Node.Text);
                output.Append($"关于{level1Title}的简介、介绍和基本情况。");
                return output.ToString();
            }


            level1Title = GetMainText(level1Node.Text);
            string level2Title = GetMainText(level2Node.Text);
            output.Append($"关于{level1Title}的{level2Title}");

            List<string> level3Titles = new List<string>();
            foreach (TreeNode level3Node in level2Node.Nodes)
            {
                string level3Title = GetMainText(level3Node.Text);
                level3Titles.Add(level3Title);
            }
            if (level3Titles.Count > 0)
            {
                output.Append("，包括了");
                output.Append(string.Join("、", level3Titles));
                output.Append("等功能。");
            }
            else
            {
                output.Append("。");
            }
            return output.ToString();
        }

        private void button_AISummary_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = GetSelectedNode();

            if (selectedNode == null)
            {
                MessageBox.Show("未勾选2级节点");
                return;
            }

            MarkdownFileContentItem item = selectedNode.Tag as MarkdownFileContentItem;
            string aiData = SummarizeSingleItem(item);
            this.textBox1.Text = GetMainKey(selectedNode) + "" + aiData;
        }

        private string SummarizeSingleItem(MarkdownFileContentItem item)
        {
            List<string> contents = new List<string>();
            for (int i = item.StartRowIndex; i <= item.EndRowIndex; i++)
            {
                if (i >= m_currentContent.ContentLines.Length)
                    continue;
                contents.Add(m_currentContent.ContentLines[i]);
            }
            var aiData = "";
            if (GlobalSetting.Instance.AIMethod == "OpenRouter")
            {
                aiData = OpenRouterUtils.SummarizeContentOfLevel3(contents);
            }
            if (GlobalSetting.Instance.AIMethod == "Ollama")
            {
                aiData = OllamaUtils.SummarizeContentOfLevel3(contents);
            }
            item.AIDescription = aiData;
            return aiData;
        }
        #endregion

        private string GetMainText(string str)
        {
            str = Regex.Replace(str, "#", "");

            var t1 = str.IndexOf("第");
            var t2 = str.IndexOf("章");
            if (t1 >= 0 && t2 > t1)
            {
                str = str.Substring(t2 + 1);
            }

            var t4 = str.IndexOf('.');
            if (t4 > 0)
            {
                var t5 = str.IndexOf(' ', t4);
                if (t5 > 0)
                {
                    if (double.TryParse(str.Substring(0, t5), out double tt))
                    {
                        str = str.Substring(t5);
                    }
                }
            }
            if (t4 > 0)
            {
                if (IsNumDotNum(str.Substring(0, t4)))
                {
                    str = str.Substring(t4 + 1);
                }
            }
            t4 = str.IndexOf(' ');
            if (t4 > 0)
            {
                if (IsNumDotNum(str.Substring(0, t4)))
                {
                    str = str.Substring(t4 + 1);
                }
            }
            str = str.Trim();

            return str;
        }
        private bool IsNumDotNum(string str)
        {
            var q = str.Split('.');
            for (var i = 0; i < q.Length; i++)
            {
                if (int.TryParse(q[i], out int n) == false)
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 先一级节点check，然后触发button2_Click（）功能。
        /// 然后每个二级节点check，然后触发button2_Click（）功能。
        /// 注意，每次只有一个节点被check
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button_exportAll_Click(object sender, EventArgs e)
        {
            m_enableAutoFileIndex = false;
            m_autoFileIndex = 1;
            m_enableAutoCheck = false;

            // 先处理一级节点
            if (treeView1.Nodes.Count > 0)
            {
                // 清除所有已选中的节点
                ClearCheckedNodes(treeView1.Nodes);

                // 选中一级节点
                treeView1.Nodes[0].Checked = true;

                ExportTitle();

                // 触发button2_Click功能
                var filePath = ExportFile();
                await UploadToMinio(filePath);
                m_autoFileIndex++;
            }

            // 处理二级节点
            foreach (TreeNode level1Node in treeView1.Nodes)
            {
                foreach (TreeNode level2Node in level1Node.Nodes)
                {
                    // 清除所有已选中的节点
                    ClearCheckedNodes(treeView1.Nodes);

                    // 选中当前二级节点
                    level2Node.Checked = true;
                    ExportTitle();

                    // 触发button2_Click功能
                    var path = ExportFile();
                    await UploadToMinio(path);
                    m_autoFileIndex++;
                }
            }
            await UploadToDify(currentTxtFilePath);
            m_enableAutoCheck = true;
        }

        #region 菜单-文件
        private void 设置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormSetting setting = new FormSetting();
            setting.ShowDialog();
        }
        private void 保存文档ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_currentContent.Save(null);
        }
        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            TreeNodeStateInfo treeNodeStateInfo = new TreeNodeStateInfo();
            treeNodeStateInfo.Save(this.treeView1);

            if (m_selectedItem == null)
            {
                m_currentContent.LoadText(this.richTextBox1.Lines);
            }
            else
            {
                var stb = new List<string>();
                for (var i = 0; i < m_selectedItem.StartRowIndex; i++)
                {
                    stb.Add(m_currentContent.ContentLines[i]);
                }
                stb.AddRange(this.richTextBox1.Lines);
                for (var i = m_selectedItem.EndRowIndex; i < m_currentContent.ContentLines.Length; i++)
                {
                    stb.Add(m_currentContent.ContentLines[i]);
                }

                m_currentContent.LoadText(stb.ToArray());
            }

            treeNodeStateInfo.Restore(this.treeView1);
        }
        private void 另存成文档ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog openFileDialog = new SaveFileDialog();
            openFileDialog.Filter = "*.md|*.md";
            openFileDialog.FileName = m_currentContent.GetNextFileName();
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                m_currentContent.Save(openFileDialog.FileName);
            }
        }
        #endregion

        private void 单项总结ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = GetSelectedNode();

            if (selectedNode == null)
            {
                MessageBox.Show("未加载数据或选中节点");
                return;
            }

            MarkdownFileContentItem item = selectedNode.Tag as MarkdownFileContentItem;
            SummarizeSingleItem(item);
        }

        private void 全部总结ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (treeView1.Nodes.Count==0)
            {
                MessageBox.Show("未加载数据");
                return;
            }

            //仅处理2级节点
            List<MarkdownFileContentItem> items_level2 = new List<MarkdownFileContentItem>();
            foreach (TreeNode level1Node in treeView1.Nodes)
            {
                foreach (TreeNode level2Node in level1Node.Nodes)
                {
                    items_level2.Add(level2Node.Tag as MarkdownFileContentItem);
                }
            }
            foreach (var item in items_level2)
            {
                SummarizeSingleItem(item);
            }
        }

        #region 工具菜单
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            AIDeleteConent aIDeleteConent = new AIDeleteConent();
            var res = aIDeleteConent.Find(m_currentContent);
            if (res[0] == -1) return;
            var fromIndex = 0;
            for (var i = 0; i < res[0]; i++)
            {
                fromIndex += m_currentContent.ContentLines[i].Length + 1;
            }
            var endIndex = fromIndex;
            for (var i = res[0]; i < res[1]; i++)
            {
                endIndex += m_currentContent.ContentLines[i].Length + 1;
            }
            this.richTextBox1.Select(fromIndex, endIndex - fromIndex);
            this.richTextBox1.ScrollToCaret();
        }
        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            // 删除 richTextBox1 中选中的内容
            string beforeSelected = this.richTextBox1.Text.Substring(0, this.richTextBox1.SelectionStart);
            string afterSelected = this.richTextBox1.Text.Substring(this.richTextBox1.SelectionStart + this.richTextBox1.SelectionLength);
            this.richTextBox1.Text = beforeSelected + afterSelected;

            TreeNodeStateInfo treeNodeStateInfo = new TreeNodeStateInfo();
            treeNodeStateInfo.Save(this.treeView1);

            m_currentContent.LoadText(this.richTextBox1.Lines);

            treeNodeStateInfo.Restore(this.treeView1);
        }
        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            FindContentForm form = new FindContentForm()
            {
                CurrentContent = this.m_currentContent
            };
            form.OnOkCick = (se, e2) =>
            {
                for (var i = 0; i < form.items.Count; i++)
                {
                    var item = form.items[i];
                    var newLine = new StringBuilder();
                    for (int j = 0; j < item.Level + 1; j++)
                    {
                        newLine.Append('#');
                    }
                    // 添加一个空格
                    newLine.Append(' ');
                    newLine.Append(item.line);
                    m_currentContent.ContentLines[item.rowIndex] = newLine.ToString();
                }
                m_currentContent.LoadText(m_currentContent.ContentLines);
            };
            form.Show();
        }
        /// <summary>
        /// 显示全文
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            var sb = new StringBuilder();
            for (var i = 0; i < m_currentContent.ContentLines.Length; i++)
            {
                sb.AppendLine(m_currentContent.ContentLines[i]);
            }
            this.richTextBox1.Text = sb.ToString();

            m_selectedItem = null;
        }

        #endregion

        #region 目录树
        private void 删除章节包括子节点ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 获取当前选中的节点
            TreeNode selectedNode = treeView1.SelectedNode;
            if (selectedNode == null)
            {
                return;
            }

            TreeNodeStateInfo treeNodeStateInfo = new TreeNodeStateInfo();
            treeNodeStateInfo.Save(this.treeView1);

            var item = selectedNode.Tag as MarkdownFileContentItem;

            var bi = new List<string>();
            bi.AddRange(m_currentContent.ContentLines);
            for (var i = item.EndRowIndex - 1; i >= item.StartRowIndex; i--)
            {
                bi.RemoveAt(i);
            }
            m_currentContent.LoadText(bi.ToArray());
            selectedNode.Remove();

            treeNodeStateInfo.Restore(this.treeView1);
        }

        private void 降级ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (m_selectedItem == null) return;
            TreeNodeStateInfo treeNodeStateInfo = new TreeNodeStateInfo();
            treeNodeStateInfo.Save(this.treeView1);
            m_selectedItem.DescreaseLevel(m_currentContent);
            m_currentContent.LoadText(m_currentContent.ContentLines);
            treeNodeStateInfo.Restore(this.treeView1);
        }

        private void 升级ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (m_selectedItem == null) return;
            TreeNodeStateInfo treeNodeStateInfo = new TreeNodeStateInfo();
            treeNodeStateInfo.Save(this.treeView1);
            m_selectedItem.IncreaseLevel(m_currentContent);
            m_currentContent.LoadText(m_currentContent.ContentLines);
            treeNodeStateInfo.Restore(this.treeView1);
        }
        #endregion
    }
}
